package priv.wangy.micro.common.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.micrometer.common.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;

/**
 * Json工具类
 * Jackson实现
 *
 * @author 张嘉琪
 * @since 2022-01-29
 */
public class JsonUtil {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    private static final ObjectMapper MAPPER_WITH_EMPTY = new ObjectMapper();

    static {
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true);
        MAPPER.configure(SerializationFeature.INDENT_OUTPUT, false);
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

        MAPPER_WITH_EMPTY.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        MAPPER_WITH_EMPTY.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true);
        MAPPER_WITH_EMPTY.configure(SerializationFeature.INDENT_OUTPUT, false);
        MAPPER_WITH_EMPTY.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    /**
     * Json转对象
     */
    public static <T> T readJson(String json, Class<T> tClass) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        T t;
        try {
            t = MAPPER.readValue(json, tClass);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return t;
    }

    /**
     * Json转对象
     */
    public static <T> T readJson(String json, Type type) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        JavaType javaType = MAPPER.getTypeFactory().constructType(type);
        T t;
        try {
            t = MAPPER.readValue(json, javaType);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return t;
    }

    /**
     * Json转List对象
     */
    public static <T> List<T> readJsonList(String json, Class<T> tClass) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        JavaType type = MAPPER.getTypeFactory().constructParametricType(ArrayList.class, tClass);
        List<T> t;
        try {
            t = MAPPER.readValue(json, type);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return t;
    }

    /**
     * Json转Map对象
     */
    public static <T> Map<String, T> readJsonMap(String json, Class<T> tClass) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        JavaType type = MAPPER.getTypeFactory().constructParametricType(HashMap.class, String.class, tClass);
        Map<String, T> t;
        try {
            t = MAPPER.readValue(json, type);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return t;
    }

    /**
     * Json转对象，用于{@code K<V>}格式的复杂对象
     */
    public static <K, V> K readComplexJson(String json, Class<K> kClass, Class<V> vClass) {
        if (json == null || "".equals(json.trim())) {
            return null;
        }
        JavaType type = MAPPER.getTypeFactory().constructParametricType(kClass, vClass);
        K k;
        try {
            k = MAPPER.readValue(json, type);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return k;
    }

    /**
     * Json转对象，用于{@code K<V>}格式的复杂对象
     */
    public static <K, V> K readComplexJson(String json, Type kType, Class<V> vClass) {
        if (json == null || "".equals(json.trim())) {
            return null;
        }
        JavaType type = MAPPER.getTypeFactory().constructParametricType(TypeFactory.rawClass(kType), vClass);
        K k;
        try {
            k = MAPPER.readValue(json, type);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return k;
    }

    /**
     * 转换Json字符串,null和空串忽略
     */
    public static String writeJson(Object obj) {
        if (Objects.nonNull(obj)) {
            try {
                return MAPPER.writeValueAsString(obj);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换Json字符串,null忽略
     */
    public static String writeJsonWithEmpty(Object obj) {
        if (Objects.nonNull(obj)) {
            try {
                return MAPPER_WITH_EMPTY.writeValueAsString(obj);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
